package org.apache.commons.pool2.impl;

import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * 类的描述
 *
 * @author ztkool
 * @version v
 */
public class SecurityManagerCallStack implements CallStack {
    private final String messageFormat;
    private final DateFormat dateFormat;
    private final SecurityManagerCallStack.PrivateSecurityManager securityManager;
    private volatile SecurityManagerCallStack.Snapshot snapshot;

    public SecurityManagerCallStack(String messageFormat, boolean useTimestamp) {
        this.messageFormat = messageFormat;
        this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null;
        this.securityManager = (SecurityManagerCallStack.PrivateSecurityManager) AccessController.doPrivileged(new PrivilegedAction<SecurityManagerCallStack.PrivateSecurityManager>() {
            public SecurityManagerCallStack.PrivateSecurityManager run() {
                return new SecurityManagerCallStack.PrivateSecurityManager();
            }
        });
    }

    @Override
    public boolean printStackTrace(PrintWriter writer) {
        SecurityManagerCallStack.Snapshot snapshotRef = this.snapshot;
        if (snapshotRef == null) {
            return false;
        } else {
            String message;
            if (this.dateFormat == null) {
                message = this.messageFormat;
            } else {
                DateFormat var4 = this.dateFormat;
                synchronized (this.dateFormat) {
                    message = this.dateFormat.format(snapshotRef.timestamp);
                }
            }

            writer.println(message);
            Iterator var7 = snapshotRef.stack.iterator();

            while (var7.hasNext()) {
                WeakReference<Class<?>> reference = (WeakReference) var7.next();
                writer.println(reference.get());
            }

            return true;
        }
    }

    @Override
    public void fillInStackTrace() {
        this.snapshot = new SecurityManagerCallStack.Snapshot(this.securityManager.getCallStack());
    }

    @Override
    public void clear() {
        this.snapshot = null;
    }

    private static class Snapshot {
        private final long timestamp;
        private final List<WeakReference<Class<?>>> stack;

        private Snapshot(List<WeakReference<Class<?>>> stack) {
            this.timestamp = System.currentTimeMillis();
            this.stack = stack;
        }
    }

    private static class PrivateSecurityManager extends SecurityManager {
        private PrivateSecurityManager() {
        }

        private List<WeakReference<Class<?>>> getCallStack() {
            Class<?>[] classes = this.getClassContext();
            List<WeakReference<Class<?>>> stack = new ArrayList(classes.length);
            Class[] var3 = classes;
            int var4 = classes.length;

            for (int var5 = 0; var5 < var4; ++var5) {
                Class<?> klass = var3[var5];
                stack.add(new WeakReference(klass));
            }

            return stack;
        }
    }
}
